package org.com.cis.cf;

import java.text.NumberFormat;

public class ListMF extends MF {

	void iterate() {
		int user, item, jtem, irate, jrate, f;
		double total_real, total_predict, gradient;
		for (user = 1; user <= userNumber; ++user) {
			int trainSize = trainSet.get(user).size();

			total_real = 0.0;
			total_predict = 0.0;

			for (int j = 0; j != trainSize; ++j) {
				jtem = trainSet.get(user).get(j) / 10;
				jrate = trainSet.get(user).get(j) % 10;

				total_real += Math.exp(jrate);
				total_predict += Math.exp(predict(user, jtem));
			}

			for (int i = 0; i != trainSize; ++i) {
				item = trainSet.get(user).get(i) / 10;
				irate = trainSet.get(user).get(i) % 10;

				gradient = Math.exp(irate) / total_real -  Math.exp(predict(user, item)) / total_predict;

				for (f = 0; f != factorNumber; ++f) {
					double u_f = userFactor.getQuick(user, f);
					double i_f = itemFactor.getQuick(item, f);

					double delta_u = gradient * i_f - regularization * u_f;
					userFactor.setQuick(user, f, userFactor.getQuick(user, f) + learnRate * delta_u);

					double delta_i = gradient * u_f - regularization * i_f;
					itemFactor.setQuick(item, f, itemFactor.getQuick(item, f) + learnRate * delta_i);
				}
			}
		}
	}
	
	public void runModel()
	{
		for ( int r = 1; r <= maxIteration; ++r) {
			iterate();
			//ArrayList<Double> trainNdcg = calcNdcg(trainSet);
			double testNdcg1 = calcNdcg(testSet, 1, true);
			double testNdcg2 = calcNdcg(testSet, 2, true);
			double testNdcg3 = calcNdcg(testSet, 3, true);
			double testNdcg4 = calcNdcg(testSet, 4, true);
			double testNdcg5 = calcNdcg(testSet, 5, true);
			double testNdcg10 = calcNdcg(testSet, 10, true);
			double trainNdcg10 = calcNdcg(trainSet, 10, true);
			System.out.print("iteration: " + r);
			
			NumberFormat nFormat=NumberFormat.getNumberInstance(); 
		    nFormat.setMaximumFractionDigits(4);
		    
		    System.out.print("\t" + nFormat.format(testNdcg1) + "  " + 
		    		nFormat.format(testNdcg2) + "  " + 
		    		nFormat.format(testNdcg3) + "  " + 
		    		nFormat.format(testNdcg4) + "  " + 
		    		nFormat.format(testNdcg5) + "  " + 
		    		nFormat.format(testNdcg10) + "  " +
		    		nFormat.format(trainNdcg10));
		    System.out.println();
/*			for ( int i = 0; i != testNdcg.size(); ++i) {
				System.out.print(nFormat.format(testNdcg.get(i)) + "\t");
			}
			System.out.println("\n");*/
		}
	}
}